<?php
/**
 * user model
 *
 * @author raphael seebacher <raphasee@ee.ethz.ch>
 * @version 0.01
 */
class user extends db_model {
    protected $user_exists_in_db = false;
    protected $data = Array(
      'id' => NULL,
      'name' => NULL,
      'screen_name' => NULL,
      'first_time_seen' => NULL
    );

    public function __construct($id=NULL) {
        parent::__construct();

        if ($id != NULL && intval($id)) {
            $id_clean = self::$dbc->escape(intval($id));
            $q = 'SELECT * FROM user '
                .'WHERE id='.$id_clean;
            $data = self::$dbc->query_assoc($q);

            if ($data == NULL || !is_array($data) || count($data)!=1) {
                throw new model_exception('Given id is invalid.');
            }
            else {
                $this->data=$data[0];
                $this->user_exists_in_db = true;
            }
        }
    }

    public function set($key, $value) {
        if (array_key_exists($key, $this->data)) {
            if (($key == 'id') && ($this->data[$key] != NULL)) {
                throw new model_exception('Field id of user cannot be changed.');
            }
            else {
                $this->data[$key] = $value;
                return true;
            }
        }
        else {
            throw new model_exception('Key "'.$key.'" not valid for model');
        }
    }

    public function get_id() {
        return $this->get('id');
    }

    public function get_name() {
        return $this->get('name');
    }

    public function get_screen_name() {
        return $this->get('screen_name');
    }

    public function delete() {
        try {
            $certificate = $this->get_current_certificate();
            $certificate->revoke();
        }
        catch (model_exception $e) {

        }        

        $q = 'DELETE FROM user WHERE id='.$this->get_id();
        
        foreach (array_keys($this->data) as $key) {
            $this->data[$key] = NULL;
        }
        $this->user_exists_in_db = false;

        return self::$dbc->query_assoc($q);
    }

    public function save() {
        $this->escape_data();

        if ($this->user_exists_in_db) {
            $q = 'UPDATE user SET '
                .'name=\''.($this->data['name']).'\', '
                .'screen_name=\''.($this->data['screen_name']).'\', '
                .'last_update=NOW() '
                .'WHERE id='.$this->data['id'];
        }
        else {
            $q = 'INSERT INTO user (id, name, screen_name, first_time_seen) '
                .'VALUES ('
                .($this->data['id']).', '
                .'\''.($this->data['name']).'\', '
                .'\''.($this->data['screen_name']).'\', '
                .'NOW()'
                .')';
        }

        return self::$dbc->query_assoc($q);
    }

    public static function create_from_user_credentials($user_credentials) {
        try {
            $credentials =
                user_credentials::get_by_credentials_server_credentials_id(
                  $user_credentials->get('access_token'),
                  $user_credentials->get('access_token_secret'),
                  $user_credentials->get('server_credentials_id')
                );

            return new user($credentials->get('user_id'));
        }
        catch (tds_exception $e) {
            throw new error('No user found for given credentials.');
        }
    }

    public function get_credentials() {
        return user_credentials::get_by_user_id($this->get('id'));
    }

    public function set_new_credentials($new_user_credentials) {
        try {
            $credentials = $this->get_credentials(
              $new_user_credentials->get('server_credentials_id')
            );
            $credentials->revoke();
        }
        catch (error $e) {

        }

        $new_user_credentials->set('user_id', $this->data['id']);
        $new_user_credentials->save();
    }

    public function get_location_reports() {
        return location_report::get_user_location_reports($this->data['id']);
    }

    public function get_neighbors($radius) {
        try {
            $lr = location_report::get_newest_location_report($this->data['id']);
            $lr_nearby = $lr->get_location_report_nearby($radius);

            $neighbors = Array();

            foreach ($lr_nearby as $l) {
                $neighbors[] = new user($l->get('user_id'));
            }

            return $neighbors;
        }
        catch (model_exception $e) {
            return Array();
        }
    }

    public function get_connections() {
        return user_connection::get_by_user_id($this->get('id'));
    }

    public function get_mac($connection_type) {
        try {
            $connection = user_connection::get_by_user_id_connection_type(
              $this->get('id'), $connection_type
            );
        }
        catch (model_exception $e) {
            throw new error($e->getMessage());
        }

        return $connection->get('mac');
    }

    public function get_current_certificate() {
        return user_certificate::get_current_certificate($this->get('id'));
    }

    public function get_ff() {
        $q = 'SELECT DISTINCT follower_id AS ff_id '
            .'FROM user_follower '
            .'JOIN user ON user_follower.follower_id=user.id '
            .'WHERE user_id='.$this->get('id').' '
            .'ORDER BY name ASC';
        $ffs = self::$dbc->query_assoc($q);

        $ff_users = Array();
        foreach ($ffs as $ff) {
            $ff_users[] = new user($ff['ff_id']);
        }

        return $ff_users;
    }

    public function get_ff_ids() {
        $q = 'SELECT DISTINCT follower_id AS ff_id '
            .'FROM user_follower '
            .'WHERE user_id='.$this->get('id');
        $ffs = self::$dbc->query_assoc($q);

        $result = Array();
        foreach ($ffs as $ff) {
            $result[] = $ff['ff_id'];
        }

        return $result;
    }
}